/*
 * Object   : CNetMgr
 * Type     : Backend
 *
 * Narrator : Kamran H. Khan 
 * Email    : KAMRAN.KHAN@MaximaLabssolutions.com, KAMRANHK@gmail.com
 * 
 * Copyright :
 *            MaximaLabs Solutions (R) 2009
 * 
 * 
 * Description: 
 * Provides TCP server/client functionalities. object factory pattern
 * 
 * Revision History:
 * 
 * Date(MMM/dd/yy)      Owner           Description
 * ----------------------------------------------------------------------------------------------------------------------------------------------
 * May/30/09            Kamran H. Khan  Added skeleton code
 * May/30/09            Kamran H. Khan  Added more methods
 * 
 * 
 * 
*/


using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Maxima.Common;
using System.Threading;
//using System.Windows.Forms;


namespace Maxima.Comlib
{
    public abstract class CNetMgr //: Control
    {
        //CServer m_theServer = null;
        //CClient m_theClient = null;

        protected const int READ_BUFFER_MAX_SIZE = 1024;// Client size
        //protected int MSG_SIZE_1KB = 1024; //Server size
        protected int NO_OF_MAX_CLIENTS_SUPPORTED = 10;
        protected string CLOSE_CONNECTION_REQUEST_CODE = "logout";

        public delegate void StatusChangeEventHandler(string strData, bool bIsServer);
        public event StatusChangeEventHandler OnStatusChange;


        private bool m_bIsServer;
        public bool IsServer
        {
            get { return m_bIsServer; }
            set { m_bIsServer = value; }
        }

        private string m_strIP;
        [Category("Settings")]
        [Description("IP Address")]
        [BrowsableAttribute(true)]
        public string IP
        {
            get { return m_strIP; }
            set { m_strIP = value; }
        }

        private int m_nPort;

        [Category("Settings")]
        [Description("Port")]
        [BrowsableAttribute(true)]
        public int Port
        {
            get { return m_nPort; }
            set { m_nPort = value; }
        }

        Thread m_thdParallel = null;
        /// <summary>
        /// Initializes a new instance of the <see cref="CNetMgr"/> class.
        /// </summary>
        /// <param name="strIP">The STR IP.</param>
        /// <param name="nPort">The n port.</param>
        /// <param name="bRunAsServer">if set to <c>true</c> [b run as server].</param>
        public CNetMgr(string strIP, int nPort, bool bRunAsServer)
        {
            //LogEx.Info( "Middleware Simulator [Version v2.0]");
            //LogEx.Info( "(c) Copyright MaximaLabs 2012");

            //LogEx.Info( "Starting network manager...");

            m_bIsServer = bRunAsServer;
            m_nPort = nPort;
            m_strIP = strIP;

            //LogEx.Info( "Initialization success.");

        }

        public CNetMgr()
        {


            //LogEx.Info( "Starting network manager...");

            //m_bIsServer = true;
            m_nPort = Constants.DEFAULT_PORT;
            m_strIP = System.Net.IPAddress.Any.ToString();// "91.73.78.25"; //GetPublicIP();test

            if (m_thdParallel == null)
            {
                m_thdParallel = new Thread(delegate() { GetPublicIPEx(); });
                m_thdParallel.IsBackground = true;
                m_thdParallel.Start();
            }
        }

        /// <summary>
        /// M_thes the client_ on status change.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        void m_theClient_OnStatusChange(string strData)
        {
            //LogEx.Info( "Inside");

            if (OnStatusChange != null)
                OnStatusChange(strData, false);

            //LogEx.Info( "End");

        }

        /// <summary>
        /// M_thes the server_ on status change.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        void m_theServer_OnStatusChange(string strData)
        {
            //LogEx.Info( "Inside");

            if (OnStatusChange != null)
                OnStatusChange(strData, true);
            //LogEx.Info( "End");
        }

        public abstract void Connect();
        public abstract void Stop();
        public abstract int Send(string msg);


        protected string GetPublicIP()
        {
            LogEx.Info("Getting public IP");

            string strIP = string.Empty;
            var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create("http://ifconfig.me");

            request.UserAgent = "curl"; // this simulate curl linux command

            string publicIPAddress;

            request.Method = "GET";
            try
            {
                using (System.Net.WebResponse response = request.GetResponse())
                {
                    using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
                    {
                        publicIPAddress = reader.ReadToEnd();
                        strIP = publicIPAddress.Replace("\n", "");
                        LogEx.Info("Found, " + strIP);

                    }
                }

            }
            catch (TimeoutException e)//Timeout exception to be captured
            {
                strIP = GetPublicIPEx();
            }
            catch (Exception e)
            {
                throw e;
            }

            return strIP;
        }

        //to be used, if the GetPublicIP is timedout
        public string GetPublicIPEx()
        {
            //LogEx.Info("Getting public IPEx");

            string url = "http://checkip.dyndns.org";
            System.Net.WebRequest req = System.Net.WebRequest.Create(url);
            System.Net.WebResponse resp = req.GetResponse();
            System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
            string response = sr.ReadToEnd().Trim();
            string[] a = response.Split(':');
            string a2 = a[1].Substring(1);
            string[] a3 = a2.Split('<');
            string a4 = a3[0];
            LogEx.Info("Found, Public IP: " + a4);

            return a4;
        }
    }
}
